#ifndef _MADT_H
#define _MADT_H

#include "sdt.h"

#define ACPI_MADT_LAPIC 0x0  // Local APIC
#define ACPI_MADT_IOAPIC 0x1 // I/O APIC
#define ACPI_MADT_INTSO 0x2  // Interrupt Source Override

/**
 * @brief ACPI Interrupt Controller Structure (ICS) Header
 *
 */
typedef struct ACPI_Interrupt_Controller_Structure {
    u8 type;
    u8 length;
} packed ics_hdr_t;

/**
 * @brief ACPI Processor Local APIC Structure (PLAS)
 * This structure tell information about our Local APIC per processor. Including
 * the MMIO addr.
 */
typedef struct ACPI_Processor_Local_APIC_Structure {
    ics_hdr_t header;
    u8 processor_id;
    u8 apic_id;
    u32 flags;
} packed plas_t;

/**
 * @brief ACPI IO APIC Structure (IOAS)
 *
 * This structure tell information about our I/O APIC on motherboard. Including
 * the MMIO addr.
 *
 */
typedef struct ACPI_IO_APIC_Structure {
    ics_hdr_t header;
    u8 ioapic_id;
    u8 reserved;
    u32 ioapic_addr;
    // The global system interrupt offset for this IOAPIC. (Kind of IRQ offset for a slave IOAPIC)
    u32 gis_offset;
} packed ioas_t;

/**
 * @brief ACPI Interrupt Source Override (INTSO)
 *
 * According to the ACPI Spec, the IRQ config between APIC and 8259 PIC can be
 * assumed to be identically mapped. However, some manufactures may have their
 * own preference and hence expections may be introduced. This structure provide
 * information on such exception.
 *
 */
typedef struct ACPI_Interrupt_Source_Override {
    ics_hdr_t header;
    u8 bus;
    // source, which is the original IRQ back in the era of IBM PC/AT,
    // the 8259 PIC
    u8 source;
    // global system interrupt. The override of source in APIC mode
    u32 gsi;
    u16 flags;
} packed intso_t;

/**
 * @brief ACPI Multiple APIC Descriptor Table (MADT)
*/
typedef struct ACPI_Multiple_APIC_Descriptor_Table {
    sdth_t header;
    void* apic_addr;
    u32 flags;
} packed madt_t;

typedef struct acpi_madt_context {
    void* apic_addr;
    plas_t* apic;
    ioas_t* ioapic;
    intso_t** irq_exception;
} packed madt_ctx_t;

#endif /* _MADT_H */
